<script lang="ts">
  import Spacer from '$lib/Layout/Spacer.svelte';
  import settings from '$stores/settings';
  import ParallaxImage from '../../../lib/Image/ParallaxImage.svelte';
  import { typeSchedule, type ParseResult } from '$lib/Hololive/hololive';
  import HeadTitle from '$lib/Home/HeadTitle.svelte';
  import Message from '$lib/Loading/Message.svelte';
  import { estimatedDayReading } from '$lib/Media/Manga/time';
  import Skeleton from '$lib/Loading/Skeleton.svelte';
  import root from '$lib/Utility/root';
  import locale from '$stores/locale';
  import { onMount } from 'svelte';
  import authorisedUsers from '$lib/Data/Static/authorised.json';
  import tooltip from '$lib/Tooltip/tooltip';
  import AnimeRateLimited from '$lib/Error/AnimeRateLimited.svelte';
  import identity from '$stores/identity';
  import SettingHint from '$lib/Settings/SettingHint.svelte';
  import proxy from '$lib/Utility/proxy';
  import { parseScheduleHtml } from '$lib/Data/hololive';
  import type { Preferences } from '../../../graphql/$types';
  import SvelteMarkdown from '@humanspeak/svelte-markdown';
  import MarkdownLink from '$lib/MarkdownLink.svelte';
  import LinkedTooltip from '$lib/Tooltip/LinkedTooltip.svelte';
  import { graphql } from '$houdini';

  export let data;

  $: ({ Profile } = data);
  $: preferences = $Profile.fetching
    ? undefined
    : ($Profile.data?.User?.preferences as Preferences | undefined);

  const setCategoriesQuery = graphql(`
    mutation SetCategories($categories: [String!]!) {
      setPinnedBadgeWallCategories(categories: $categories) {
        id

        preferences {
          pinned_badge_wall_categories
        }
      }
    }
  `);

  const toggleCategoryQuery = graphql(`
    mutation ToggleCategory($category: String!) {
      togglePinnedBadgeWallCategory(category: $category) {
        id

        preferences {
          pinned_badge_wall_categories
        }
      }
    }
  `);

  const toggleHideMissingBadgesQuery = graphql(`
    mutation ToggleHideMissingBadges {
      toggleHideMissingBadges {
        id

        preferences {
          hide_missing_badges
        }
      }
    }
  `);

  const toggleHideAWCBadgesQuery = graphql(`
    mutation ToggleHideAWCBadges {
      toggleHideAWCBadges {
        id

        preferences {
          hide_awc_badges
        }
      }
    }
  `);

  const setBiographyQuery = graphql(`
    mutation SetBiography($biography: String!) {
      setBiography(biography: $biography) {
        id

        preferences {
          biography
        }
      }
    }
  `);

  const setBadgeWallCSSQuery = graphql(`
    mutation SetBadgeWallCSS($css: String!) {
      setBadgeWallCSS(css: $css) {
        id

        preferences {
          badge_wall_css
        }
      }
    }
  `);

  $: userData = data.userData;

  let error = false;
  let schedule: ParseResult | undefined = undefined;
  let draggedCategory: string | null = null;
  let draggedOverCategory: string | null = null;

  $: displayBadges = (username: string, badges: number | string) =>
    $locale({
      values: {
        badges: badges,
        username
      }
    }).user.profile.badges;

  const handleDragStart = (
    event: DragEvent & { currentTarget: EventTarget & HTMLDivElement },
    category: string | null
  ) => {
    draggedCategory = category;

    if (event.dataTransfer) event.dataTransfer.effectAllowed = 'move';
  };

  const handleDragOver = (event: DragEvent) => {
    event.preventDefault();

    if (event.dataTransfer) event.dataTransfer.dropEffect = 'move';
  };

  const handleDragEnter = (
    event: DragEvent & { currentTarget: EventTarget & HTMLDivElement },
    category: string | null
  ) => {
    event.preventDefault();

    if (draggedCategory !== category && preferences && draggedCategory) {
      draggedOverCategory = category;

      const categories = preferences.pinned_badge_wall_categories;
      const draggedIndex = categories.indexOf(draggedCategory);
      const targetIndex = categories.indexOf(category || '');

      categories.splice(draggedIndex, 1);
      categories.splice(targetIndex, 0, draggedCategory);

      preferences.pinned_badge_wall_categories = categories;
    }
  };

  const handleDragLeave = (
    event: DragEvent & { currentTarget: EventTarget & HTMLDivElement },
    category: string
  ) => {
    event.preventDefault();

    if (draggedOverCategory === category && preferences && draggedCategory) {
      draggedOverCategory = null;

      const categories = preferences.pinned_badge_wall_categories;
      const draggedIndex = categories.indexOf(draggedCategory);

      categories.splice(draggedIndex, 1);
      categories.splice(categories.indexOf(category) + 1, 0, draggedCategory);

      preferences.pinned_badge_wall_categories = categories;
    }
  };

  const handleDrop = (event: { preventDefault: () => void }) => {
    event.preventDefault();

    if (userData && preferences)
      setCategoriesQuery
        .mutate({
          categories: preferences.pinned_badge_wall_categories
        })
        .then();

    draggedCategory = null;
    draggedOverCategory = null;
  };

  onMount(async () => {
    schedule = typeSchedule(
      parseScheduleHtml(
        await (
          await fetch(proxy('https://schedule.hololive.tv'), {
            headers: {
              Cookie: 'timezone=Asia/Tokyo'
            }
          })
        ).text()
      )
    );
  });

  const getBadgeWallCSS = () =>
    (document.getElementById('badgeWallCSS') as HTMLTextAreaElement).value;

  const getBiography = () =>
    (document.getElementById('biography') as HTMLTextAreaElement).value.slice(0, 3000);

  const toggleCategory = () => {
    if (!userData) return;

    const categoryElement = document.getElementById('category') as HTMLInputElement;
    const category = categoryElement.value;

    toggleCategoryQuery.mutate({ category }).then();

    categoryElement.value = '';
  };

  // 8.5827814569536423841e0
</script>

<HeadTitle route={`${data.username}'s Profile`} path={`/user/${data.username}`} />

{#if error}
  <AnimeRateLimited>
    <a href={`https://anilist.co/user/${data.username}`} target="_blank">@{data.username}</a>'s
    profile could not be loaded.
  </AnimeRateLimited>
{:else}
  {#if userData === null}
    <Message slot withReload>
      <p>
        Could not load user profile for <a
          href={`https://anilist.co/user/${data.username}`}
          target="_blank">@{data.username}</a
        >.
      </p>
    </Message>
  {:else if userData === undefined}
    <Skeleton card={false} bigCard count={1} height="224px" />

    <Message message="Loading user profile ..." />
  {:else}
    <div class="card card-small">
      <div
        class="card user-grid"
        style={`background-image: ${
          userData ? `url(${userData.bannerImage})` : 'none'
        }; padding: 0;`}
      >
        {#if userData}
          <img src={userData.bannerImage} alt="" class="cover-image" />
        {/if}

        <div class="card user-grid-content">
          <div class="user-grid-avatar">
            <LinkedTooltip content={`${userData.name}`} id="avatar" pin="avatar" relative>
              <a href={`https://anilist.co/user/${userData.name}`} target="_blank">
                <ParallaxImage
                  source={$settings.displayDataSaver
                    ? userData.avatar.medium
                    : userData.avatar.large}
                  alternativeText=""
                  style="border-radius: 8px; width: 6.5em;"
                />
              </a>
            </LinkedTooltip>
          </div>

          <div class="user-grid-rest">
            <p>
              <a
                href={`https://anilist.co/user/${userData.name}`}
                target="_blank"
                title={String(userData.id)}
                use:tooltip
              >
                @{userData.name}
              </a>
              {#if userData && authorisedUsers.includes(userData.id)}
                &#8204;
                <button class="unclickable-button button-badge badge-rainbow">Owner</button>
              {/if}
              <span class="click-item separator opaque">•</span>
              <a href={root(`/user/${userData.name}/badges`)}>Badge Wall</a>
            </p>

            {#if preferences && preferences.biography && preferences.biography.length > 0}
              <SvelteMarkdown
                source={preferences.biography}
                renderers={{
                  link: MarkdownLink
                }}
              />
            {/if}

            {$locale({
              values: {
                username: userData.name,
                anime: (userData.statistics.anime.minutesWatched / 60 / 24).toFixed(1),
                manga: estimatedDayReading(userData.statistics.manga.chaptersRead).toFixed(1)
              }
            }).user.profile.statistics}

            {#if schedule && preferences && preferences.biography && preferences.biography.length > 0}
              <br />
            {:else}
              <Spacer />
            {/if}

            {#if $Profile.fetching}
              {displayBadges(userData.name, '...')}
            {:else if $Profile.data && $Profile.data.User}
              {@const badges = $Profile.data.User.badgesCount}

              {#if badges}
                {displayBadges(userData.name, badges)}
              {:else}
                {displayBadges(userData.name, '?')}
              {/if}
            {:else}
              {displayBadges(userData.name, '?')}
            {/if}
          </div>
        </div>
      </div>
    </div>
  {/if}

  {#if schedule && preferences && preferences.pinned_hololive_streams.length > 0}
    <Spacer />

    <div class="card">
      <div class="hololive-badges">
        {#each preferences.pinned_hololive_streams as stream, index}
          {@const avatar = schedule.dict[stream]}

          {#if avatar}
            <LinkedTooltip
              content={stream}
              id={`hololive-badge-${index}`}
              pin={`hololive-badge-${index}`}
              relative
            >
              <a href={root(`/hololive/${encodeURIComponent(stream)}`)}>
                <div class="user-grid-hololive-badges">
                  <ParallaxImage source={avatar} alternativeText="Avatar" />
                </div>
              </a>
            </LinkedTooltip>
          {/if}
        {/each}
      </div>
    </div>
  {/if}

  {#if preferences && userData && userData.id === $identity.id}
    <Spacer />

    <details open>
      <summary>{$locale().user.preferences.title}</summary>

      <input
        type="checkbox"
        onchange={() => {
          if (userData) toggleHideMissingBadgesQuery.mutate(null).then();
        }}
        checked={preferences.hide_missing_badges}
      />
      {$locale().user.preferences.hideMissingBadges.title}
      <SettingHint lineBreak>{$locale().user.preferences.hideMissingBadges.hint}</SettingHint>

      <Spacer />

      <input
        type="checkbox"
        onchange={() => {
          if (userData) toggleHideAWCBadgesQuery.mutate(null).then();
        }}
        checked={preferences.hide_awc_badges}
      />
      {$locale().user.preferences.hideAWCBadges.title}

      <Spacer />

      Pinned Categories

      <div class="pinned-categories">
        {#each preferences.pinned_badge_wall_categories as category}
          <div
            class="card card-small pinned-category"
            draggable="true"
            ondragstart={(event) => handleDragStart(event, category)}
            ondragover={handleDragOver}
            ondragenter={(event) => handleDragEnter(event, category)}
            ondragleave={(event) => handleDragLeave(event, category)}
            ondrop={handleDrop}
            role="button"
            tabindex="0"
          >
            <span class="pinned-category-name">
              {category}
            </span>

            <button
              onclick={() => {
                if (userData) toggleCategoryQuery.mutate({ category }).then();
              }}>Remove</button
            >
          </div>
        {/each}

        <span class="card card-small pinned-category">
          <span class="pinned-category-name">
            <input type="text" id="category" placeholder="Category" style="width: 10em;" />
          </span>

          <button class="button-lined" onclick={toggleCategory}>Add</button>
        </span>
      </div>

      <Spacer />

      Biography

      <button
        onclick={() => {
          if (userData)
            setBiographyQuery
              .mutate({
                biography: getBiography()
              })
              .then();
        }}>Save</button
      >
      <textarea
        value={preferences.biography}
        rows="5"
        cols="100"
        id="biography"
        placeholder="Markdown supported!"
      ></textarea>

      <Spacer />

      Badge Wall Custom CSS

      <button
        onclick={() => {
          if (userData)
            setBadgeWallCSSQuery
              .mutate({
                css: getBadgeWallCSS()
              })
              .then();
        }}>Save</button
      >
      <textarea
        value={preferences.badge_wall_css}
        rows="10"
        cols="100"
        id="badgeWallCSS"
        placeholder="/* Use classes and IDs such as .badges, #badges, .badge, or standard elements like body and details, or anything, as long as it's valid CSS! */"
      ></textarea>
    </details>
  {/if}
{/if}

<style lang="scss">
  .user-grid-content {
    display: flex;
    flex-wrap: wrap;
    column-gap: 1.5em;
    background-color: rgba(0, 0, 0, 0.468);
    color: #d8d8d8;
    border-top-left-radius: 0;
    border-top-right-radius: 0;
  }

  .user-grid-avatar {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
  }

  .click-item {
    margin: 0 0.625rem;
  }

  .user-grid {
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
  }

  .cover-image {
    visibility: hidden;
    height: 4.5em;
  }

  .user-grid-hololive-badges {
    $transitionDuration: 0.45s;
    $transition:
      transform $transitionDuration ease,
      box-shadow $transitionDuration ease;
    $size: 5.25em;

    border-radius: 8px;
    width: $size;
    height: $size;
    object-fit: cover;
    transition: $transition;
    box-shadow: rgba(0, 0, 11, 0.1) 0px 7px 29px 0px;
    overflow: hidden;

    &:hover {
      z-index: 2;
      transition: $transition;
      transform: scale(1.15);
      box-shadow:
        0 1.5px 9px var(--base01),
        0 0 0 4px var(--base02),
        0 4px 30px var(--base01);
    }
  }

  .hololive-badges {
    display: flex;
    gap: 1rem;
    border-radius: 8px;
    justify-content: space-around;
    flex-wrap: wrap;
  }

  .separator {
    color: var(--base04);
  }

  .user-grid-rest {
    flex: 1;
  }

  .pinned-categories {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
  }

  .pinned-category {
    display: flex;
    align-items: center;
  }

  .pinned-category-name {
    margin-right: 0.5em;
  }
</style>
